package top.yangbuyi.controller.system;

import cn.hutool.core.date.DateUtil;
import eu.bitwalker.useragentutils.UserAgent;
import lombok.extern.log4j.Log4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import top.yangbuyi.acpect.annotaction.Log;
import top.yangbuyi.acpect.enums.BusinessType;
import top.yangbuyi.constants.Constants;
import top.yangbuyi.constants.HttpStatus;
import top.yangbuyi.domain.LoginInfo;
import top.yangbuyi.domain.Menu;
import top.yangbuyi.domain.SimpleUser;
import top.yangbuyi.dto.LoginBodyDto;
import top.yangbuyi.service.impl.LoginInfoService;
import top.yangbuyi.service.impl.MenuService;
import top.yangbuyi.utils.AddressUtils;
import top.yangbuyi.utils.IpUtils;
import top.yangbuyi.utils.ShiroSecurityUtils;
import top.yangbuyi.vo.*;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.*;


/**
 * @description: 杨不易网站:www.yangbuyi.top
 * @program: yangbuyiopenHis2020
 * @ClassName: LoginController
 * @create: 2020-08-28 10:16
 * @author: yangbuyi
 * @since： JDK1.8
 * @LoginController: 用户登录入口$
 **/

@RestController
@Log4j
public class LoginController {

	  @Autowired
	  private MenuService menuService;
	  @Autowired
	  private LoginInfoService loginInfoService;

	  /**
	   * @Description: 杨不易个人网址:http://yangbuyi.top
	   * 功能描述: 前端登录接口实现
	   * @Author: TeouBle
	   * @Date: 2020/8/28 10:47
	   */
	  @PostMapping({"login/doLogin"})
	  public AjaxResult doLogin(@RequestBody @Validated LoginBodyDto loginBodyDto, HttpServletRequest request) {
			// 进行校验
			AjaxResult ajaxResult = AjaxResult.success();
			UsernamePasswordToken token = new UsernamePasswordToken(loginBodyDto.getUsername(), loginBodyDto.getPassword());
			Subject subject = SecurityUtils.getSubject();
			LoginInfo loginInfo = createLoginInfo(request);
			// 设置登录用户名
			loginInfo.setLoginAccount(loginBodyDto.getUsername());
			try {
				  subject.login(token);
				  // 得到token===sessionID 会话
				  Serializable token_id = subject.getSession().getId();
				  // 写入日志
				  // 登录状态
				  loginInfo.setLoginStatus(Constants.LOGIN_SUCCESS);
				  // 当前 登录的名称
				  loginInfo.setUserName(ShiroSecurityUtils.getCurrentUserName() != null ?  ShiroSecurityUtils.getCurrentUserName() : "未知");
				  loginInfo.setMsg("登录成功");
				  // 返回token给到前端
				  ajaxResult.put(Constants.TOKEN, token_id);
				  // 写入日志
			} catch (Exception e) {
				  log.error("用户名或密码不正确", e);
				  ajaxResult = AjaxResult.error(HttpStatus.ERROR, "用户名或密码不正确");
				  loginInfo.setLoginStatus(Constants.LOGIN_ERROR);
				  loginInfo.setMsg("用户名或密码不正确");
			}
			System.err.println(loginInfo);
			// 保存登录信息到数据库
			loginInfoService.insertLoginInfo(loginInfo);
			System.err.println(ajaxResult);
			return ajaxResult;
	  }

	  /**
	   * 构造日志信息
	   *
	   * @param request
	   * @return
	   */
	  private LoginInfo createLoginInfo(HttpServletRequest request) {
			LoginInfo loginInfo = new LoginInfo();
			UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
			// 设置IP
			loginInfo.setIpAddr(IpUtils.getIpAddr(request));
			// 设置IP地理位置
			loginInfo.setLoginLocation(AddressUtils.getRealAddressByIP(loginInfo.getIpAddr()));
			// 设置操作系统
			String os = userAgent.getOperatingSystem().getName();
			loginInfo.setOs(!"Unknown".equals(os) ? os : "第三方操作工具");
			// 设置操作浏览器 Unknown
			String brower = userAgent.getBrowser().getName();
			loginInfo.setBrowser(!"Unknown".equals(brower) ? brower : "第三方访问工具");
			// 设置登录时间
			loginInfo.setLoginTime(DateUtil.date());
			// 设置登录类型
			loginInfo.setLoginType(Constants.LOGIN_TYPE_SYSTEM);
			return loginInfo;
	  }

	  /**
	   * @Description: 杨不易个人网址:http://yangbuyi.top
	   * 功能描述: 前端获取用户信息
	   * @Author: TeouBle
	   * @Date: 2020/8/28 10:47
	   */
	  @GetMapping({"login/getInfo"})
	  public AjaxResult getInfo() {
			ActiverUser activerUser = (ActiverUser) SecurityUtils.getSubject().getPrincipal();
			AjaxResult success = AjaxResult.success();
			success.put("username", activerUser.getUser().getUserName());
			success.put("picture", activerUser.getUser().getPicture());
			success.put("roles", activerUser.getRoles());
			success.put("permissions", activerUser.getPermissions());
			success.put("introduction", activerUser.getUser().getIntroduction());
			return success;
	  }


	  /**
	   * @Description: 杨不易个人网址:http://yangbuyi.top
	   * 功能描述: 用户退出
	   * @Author: TeouBle
	   * @Date: 2020/8/28 10:49
	   */
	  @PostMapping({"login/logout"})
	  @Log(title = "用户退出登录", businessType = BusinessType.OTHER)
	  public AjaxResult logout() {
			Subject subject = SecurityUtils.getSubject();
			subject.logout();
			return AjaxResult.success("用户退出成功");
	  }

	  /**
	   * @Description: 杨不易个人网址:http://yangbuyi.top
	   * 功能描述: 加载前端页面菜单
	   * @Param:
	   * @return:
	   * @Author: TeouBle
	   * @Date: 2020/8/28 15:07
	   */
	  @GetMapping({"login/menus"})
	  public AjaxResult getMenus() {
			Subject subject = SecurityUtils.getSubject();
			ActiverUser activerUser = (ActiverUser) subject.getPrincipal();
			// 判断是否为超级管理员
			boolean isAdmin = activerUser.getUser().getUserType().equals(Constants.USER_ADMIN);
			SimpleUser simpleUser = null;
			if (!isAdmin) {
				  // 不是
				  simpleUser = new SimpleUser(activerUser.getUser().getUserId(), activerUser.getUser().getUserName());
			}
			// 根据规则查询对应的菜单数据
			List<Menu> menus = menuService.selectMenuTree(isAdmin, simpleUser);
			List<MenuTreeVo> menuVos = new ArrayList<>();
			// 组装菜单数据
			for (Menu menu : menus) {
				  menuVos.add(new MenuTreeVo(menu.getMenuId().toString(), menu.getPath()));
			}
			return AjaxResult.success(menuVos);
	  }

	  @GetMapping("/login/dynamicMenu")
	  public AjaxResult dynamicMenu() {
			return AjaxResult.success(this.menuService.dynamicMenu());
	  }

}
